import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:shared_preferences/shared_preferences.dart';

import 'package:flutter/foundation.dart';
import 'navigation_service.dart';
import 'user_manager.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../providers/auth_provider.dart';

class HttpUtil {
  static final HttpUtil _instance = HttpUtil._internal();
  late Dio dio;

  factory HttpUtil() => _instance;

  HttpUtil._internal() {
    BaseOptions options = BaseOptions(
      baseUrl: 'https://api.misstory789.online/api/asf/',
      connectTimeout: const Duration(seconds: 15),
      receiveTimeout: const Duration(seconds: 15),
      contentType: 'application/json-patch+json',
      validateStatus: (status) => status != null,
    );
    dio = Dio(options);

    dio.interceptors.add(
      InterceptorsWrapper(
        onRequest: (options, handler) async {
          final token = await _getToken();
          if (token != null && token.isNotEmpty) {
            options.headers['Authorization'] = 'Bearer $token';

            print('已设置Authorization头'); // 调试用
          } else {
            options.headers['Authorization'] = 'Bearer ';
            print('警告: 未找到有效token'); // 调试用
          }

          // 动态获取comicType值
          final comicType = await getComicType();
          options.headers['comicType'] = comicType;
          options.headers['bundleId'] = await getBundleId();
          print('设置comicType: $comicType'); // 调试用

          return handler.next(options);
        },
        // 新增：统一在响应阶段判断 401/403
        onResponse: (response, handler) async {
          final code = response.statusCode ?? 0;
          if (code == 401 || code == 403) {
            await _handleTokenExpired();
            return handler.reject(
              DioException(
                requestOptions: response.requestOptions,
                response: response,
                type: DioExceptionType.badResponse,
                error: 'UnauthorizedOrForbidden',
              ),
            );
          }
          return handler.next(response);
        },
        onError: (DioException e, handler) async {
          print('请求错误详情: ${e.response?.data}'); // 添加更详细的错误日志
          // 兜底：如果错误里带有 401/403，也统一处理为 token 过期
          final statusCode = e.response?.statusCode;
          if (statusCode == 401 || statusCode == 403) {
            await _handleTokenExpired();
          }
          _handleError(e);
          return handler.next(e);
        },
      ),
    );
  }

  Future<String?> _getToken() async {
    return UserManager.getCurrentToken();
  }

  Future<String> getBundleId() async {
    PackageInfo packageInfo = await PackageInfo.fromPlatform();
    return packageInfo.packageName; // 在iOS上返回的是Bundle ID
  }

  // 新增：动态获取comicType值
  Future<String> getComicType() async {
    try {
      final prefs = await SharedPreferences.getInstance();
      final userType = prefs.getString('user_type');

      // 根据用户类型设置comicType
      if (userType == 'organic') {
        return '0'; // 自然量用户
      } else if (userType == 'non_organic') {
        return '1'; // 非自然量用户
      } else {
        return '0'; // 默认值
      }
    } catch (e) {
      print('获取comicType失败: $e');
      return '0'; // 默认值
    }
  }

  // 新增：统一的 token 过期处理
  Future<void> _handleTokenExpired() async {
    // 清除本地登录信息（token、refreshToken、过期时间等）
    await UserManager.clearLoginInfo();

    // 使用NavigationService获取当前context，然后获取容器
    final context = NavigationService.navigatorKey.currentContext;
    if (context != null) {
      final container = ProviderScope.containerOf(context);
      await container.read(authProvider.notifier).logout();
    }

    NavigationService.showLoginDialog();
  }

  void _handleError(DioException e) {
    switch (e.type) {
      case DioExceptionType.connectionTimeout:
        print('连接超时');
        break;
      case DioExceptionType.badResponse:
        print('服务器错误: ${e.response?.statusCode}');
        break;
      default:
        print('请求错误: ${e.message}');
    }
  }

  void printLongJson(Map<String, dynamic> json) {
    final prettyString = const JsonEncoder.withIndent('  ').convert(json);
    debugPrint(prettyString, wrapWidth: 1024); // 不会截断
  }

  // ------------------------------
  // 1. 泛型解析版本（自动转为模型对象）
  // ------------------------------

  /// 泛型GET请求（返回解析后的模型对象）
  Future<BaseResponse<T>?> getModel<T>(
    String path, {
    Map<String, dynamic>? params,
    required T Function(dynamic) fromJson,
  }) async {
    try {
      final response = await dio.get(path, queryParameters: params);
      print("url = ${response.realUri}");
      printLongJson(response.data);
      if (response.data is Map<String, dynamic>) {
        return BaseResponse.fromJson(
          response.data as Map<String, dynamic>,
          fromJson,
        );
      }
    } catch (e) {
      print("请求错误: $e");
    }
    return null;
  }

  /// 泛型POST请求（返回解析后的模型对象）
  Future<BaseResponse<T>?> postModel<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? params,
    required T Function(dynamic) fromJson,
  }) async {
    try {
      Response response = await dio.post(
        path,
        data: data,
        queryParameters: params,
      );
      print("response = %=$response");
      if (response.data is Map) {
        return BaseResponse.fromJson(
          response.data as Map<String, dynamic>,
          fromJson,
        );
      }
    } on DioException catch (e) {
      print('POST模型请求错误: ${e.message}');
    }
    return null;
  }

  // ------------------------------
  // 2. 非泛型版本（返回原始JSON数据）
  // ------------------------------

  /// 普通GET请求（返回原始JSON数据）
  Future<Map<String, dynamic>?> getJson(
    String path, {
    Map<String, dynamic>? params,
  }) async {
    try {
      Response response = await dio.get(path, queryParameters: params);
      if (response.data is Map) {
        return response.data as Map<String, dynamic>;
      }
    } on DioException catch (e) {
      print('GET原始请求错误: ${e.message}');
    }
    return null;
  }

  /// 普通POST请求（返回原始JSON数据）
  Future<Map<String, dynamic>?> postJson(
    String path, {
    dynamic data,
    Map<String, dynamic>? params,
  }) async {
    try {
      Response response = await dio.post(
        path,
        data: data,
        queryParameters: params,
      );
      print(
          "response = ${response.realUri}, data = ${response.data}, datadata= $data");
      if (response.data is Map) {
        return response.data as Map<String, dynamic>;
      }
    } on DioException catch (e) {
      print('POST原始请求错误: ${e.message}');
    }
    return null;
  }
}

class BaseResponse<T> {
  final int status;
  final String message;
  final T? result;

  BaseResponse({
    required this.status,
    required this.message,
    this.result,
  });

  factory BaseResponse.fromJson(
    Map<String, dynamic> json,
    T Function(dynamic) fromJson,
  ) {
    return BaseResponse<T>(
      status: json['status'] as int,
      message: json['message']?.toString() ?? '',
      result: json['result'] != null ? fromJson(json['result']) : null,
    );
  }
}

// 解析工具类
class JsonParser {
  // 将JSON字符串解析为指定类型
  static T? fromJson<T>(String jsonString, T Function(dynamic) fromJson) {
    try {
      final jsonMap = json.decode(jsonString);
      return fromJson(jsonMap);
    } catch (e) {
      print('JSON解析错误: $e');
      return null;
    }
  }

  // 将JSON Map解析为指定类型
  static T? fromJsonMap<T>(
    Map<String, dynamic> jsonMap,
    T Function(dynamic) fromJson,
  ) {
    try {
      return fromJson(jsonMap);
    } catch (e) {
      print('JSON Map解析错误: $e');
      return null;
    }
  }
}

/**
 
// 使用示例
class User {
  final String id;
  final String name;

  User({required this.id, required this.name});

  static User fromJson(dynamic json) {
    return User(
      id: json['id'] as String,
      name: json['name'] as String,
    );
  }
}

// 调用示例
void requestExamples() async {
  // 1. 使用泛型版本（获取模型对象）
  final userResponse = await HttpUtil().getModel(
    '/user/profile',
    params: {'id': '123'},
    fromJson: User.fromJson,
  );
  if (userResponse?.status == 0) {
    print('用户名: ${userResponse?.data?.name}'); // 直接访问模型属性
  }

  // 2. 使用非泛型版本（获取原始JSON）
  final rawResponse = await HttpUtil().postJson(
    '/login',
    data: {'username': 'test', 'password': '123'},
  );
  if (rawResponse?['status'] == 0) {
    print('登录成功: ${rawResponse?['message']}'); // 手动处理JSON
  }
}

 */
